﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace AAA.Forms.Components.Util
{
    public class DataGridViewUtil
    {
        public static readonly object TRUE_VALUE = true;
        public static readonly object FALSE_VALUE = false;

        public const int V_SCROLL_VISIBLE = 0;
        public const int V_SCROLL_WIDTH = 1;
        public const int H_SCROLL_VISIBLE = 2;
        public const int H_SCROLL_HEIGHT = 3;

        public static object[] GetScrollBarStatus(DataGridView tblSource)
        {
            object[] oValues = new object[4];

            foreach (Control control in tblSource.Controls)
            {
                if (control is HScrollBar)
                {
                    oValues[H_SCROLL_VISIBLE] = control.Visible;
                    oValues[H_SCROLL_HEIGHT]  = control.Height;
                }

                if (control is VScrollBar)
                {
                    oValues[V_SCROLL_VISIBLE] = control.Visible;
                    oValues[V_SCROLL_WIDTH] = control.Width;
                }
            }

            return oValues;
        }

        public static void AutoWrap(DataGridView tblSource, bool isAutoWrap)
        {            
            tblSource.DefaultCellStyle.WrapMode = isAutoWrap ? DataGridViewTriState.True : DataGridViewTriState.NotSet;
            tblSource.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
        }

        public static void AdjustTableHeight(DataGridView tblSource, int iDefaultHeight)
        {
            int iTableHeight = 0;
            int iScrollHeight = 0;
            tblSource.Height = iDefaultHeight;

            for (int i = 0; i < tblSource.Controls.Count; i++)
            {
                if (tblSource.Controls[i] is HScrollBar)
                {
                    if (tblSource.Controls[i].Visible)
                    {
                        iScrollHeight = tblSource.Controls[i].Height;
                    }
                }
            }

            
            iTableHeight = tblSource.ColumnHeadersVisible ? tblSource.ColumnHeadersHeight : 0;
            for (int i = 0; i < tblSource.Rows.Count; i++)
            {
                //iTableHeight += tblSource.Rows[i].Cells[0].ContentBounds.Height;
                iTableHeight += Math.Max(tblSource.Rows[i].GetPreferredHeight(i, DataGridViewAutoSizeRowMode.AllCells, false),
                                         tblSource.Rows[i].Height);
                //iTableHeight += tblSource.Rows[i].Height;
            }

            
            tblSource.Height = Math.Min(tblSource.Height, iTableHeight + iScrollHeight + tblSource.ColumnHeadersHeight + 40);

        }

        public static void AutoFitColumn(DataGridView tblSource)
        {
            AutoFitColumn(tblSource, DataGridViewAutoSizeColumnMode.DisplayedCells);
        }

        public static void AutoFitColumn(DataGridView tblSource, DataGridViewAutoSizeColumnMode resizeMode)
        {
            if (tblSource.Rows.Count == 0)
            {
                for(int i = 0; i < tblSource.Columns.Count; i++)
                    tblSource.Columns[i].Width = (int)Math.Floor((double)tblSource.Width / tblSource.Columns.Count) - 2;
                return;
            }

            for (int i = 0; i < tblSource.Columns.Count; i++)
                tblSource.Columns[i].AutoSizeMode = resizeMode;
        }

        public static void Clear(DataGridView tblSource)
        {
            Clear(tblSource, false);
        }
        
        public static void Clear(DataGridView tblSource, bool isClearColumn)
        {
            if (isClearColumn)
            {
                while (tblSource.Columns.Count > 0)
                    tblSource.Columns.RemoveAt(0);
                return;
            }

            while (tblSource.Rows.Count > 0)
                tblSource.Rows.RemoveAt(0);
        }

        private static void Insert(DataGridView tblSource, object[] oValues)
        {
            tblSource.Rows.Add(oValues);
        }

        public static void InsertRow(DataGridView tblSource, object[] oValues) 
        {
            if (tblSource.InvokeRequired)
            {
                tblSource.Invoke((MethodInvoker)delegate()
                {
                    Insert(tblSource, oValues);

                });
            }
            else
            {
                Insert(tblSource, oValues);
            }                

        }

        public static int FindRowIndex(DataGridView tblSource, string[] strKeyFields, object[] oValues)
        {
            bool isMatch;
            int[] iColumnIndex;

            iColumnIndex = new int[strKeyFields.Length];
            for (int i = 0; i < iColumnIndex.Length; i++)
            {
                iColumnIndex[i] = tblSource.Columns.IndexOf(tblSource.Columns[strKeyFields[i]]);
            }

            for (int iRowIndex = 0; iRowIndex < tblSource.Rows.Count; iRowIndex++)
            {
                isMatch = true;
                for (int i = 0; i < strKeyFields.Length; i++)
                {
                    if (tblSource.Rows[iRowIndex].Cells[strKeyFields[i]].Value.ToString() != oValues[i].ToString())
                    {
                        isMatch = false;
                        break;
                    }
                }
                if (isMatch)
                    return iRowIndex;
            }
            return -1;
        }

        private static void UpdateGivenRow(DataGridView tblSource, int iRowIndex, object[] oValues)
        {
            try
            {
                for (int i = 0; i < tblSource.Columns.Count; i++)
                    tblSource.Rows[iRowIndex].Cells[i].Value = oValues[i];
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        private static void Update(DataGridView tblSource, string[] strKeyFields, object[] oOldValues, object[] oNewValues)
        {
            bool isMatch;
            int[] iColumnIndex;
            try
            {
                iColumnIndex = new int[strKeyFields.Length];
                for(int i = 0; i < iColumnIndex.Length; i++)
                {
                    iColumnIndex[i] = tblSource.Columns.IndexOf(tblSource.Columns[strKeyFields[i]]);
                }

                for(int iRowIndex = 0; iRowIndex < tblSource.Rows.Count; iRowIndex++)
                {
                    isMatch = true;
                    for (int i = 0; i < strKeyFields.Length; i++)
                    {
                        if(tblSource.Rows[iRowIndex].Cells[strKeyFields[i]].Value.ToString() != oOldValues[iColumnIndex[i]].ToString())
                        {
                            isMatch = false;
                            break;
                        }
                    }
                    if(isMatch)
                    {
                        for (int i = 0; i < tblSource.Columns.Count; i++)
                            tblSource.Rows[iRowIndex].Cells[i].Value = oNewValues[i];
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public static void UpdateRow(DataGridView tblSource, int iRowIndex, object[] oValues)
        {
            if (tblSource.InvokeRequired)
            {
                tblSource.Invoke((MethodInvoker)delegate()
                {
                    UpdateGivenRow(tblSource, iRowIndex, oValues);

                });
            }
            else
            {
                UpdateGivenRow(tblSource, iRowIndex, oValues);
            }
        }

        public static void UpdateRow(DataGridView tblSource, string[] strKeyFields, object[] oValues)
        {
            UpdateRow(tblSource, strKeyFields, oValues, oValues);
        }

        public static void UpdateRow(DataGridView tblSource, string[] strKeyFields, object[] oOldValues, object[] oNewValues)
        {
            if (tblSource.InvokeRequired)
            {
                tblSource.Invoke((MethodInvoker)delegate()
                {
                    Update(tblSource, strKeyFields, oOldValues, oNewValues);

                });
            }
            else
            {
                Update(tblSource, strKeyFields, oOldValues, oNewValues);
            }
        }

        private static void Delete(DataGridView tblSource, string[] strKeyFields, object[] oValues)
        {
            bool isMatch;
            int[] iColumnIndex;
            try
            {
                iColumnIndex = new int[strKeyFields.Length];
                for (int i = 0; i < iColumnIndex.Length; i++)
                {
                    iColumnIndex[i] = tblSource.Columns.IndexOf(tblSource.Columns[strKeyFields[i]]);
                }

                for (int iRowIndex = tblSource.Rows.Count - 1; iRowIndex >= 0; iRowIndex--)
                {
                    isMatch = true;
                    for (int i = 0; i < strKeyFields.Length; i++)
                    {
                        if (tblSource.Rows[iRowIndex].Cells[strKeyFields[i]].Value.ToString() != oValues[iColumnIndex[i]].ToString())
                        {
                            isMatch = false;
                            break;
                        }
                    }
                    if (isMatch)
                        tblSource.Rows.RemoveAt(iRowIndex);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public static void DeleteRow(DataGridView tblSource, string[] strKeyFields, object[] oValues)
        {
            if (tblSource.InvokeRequired)
            {
                tblSource.Invoke((MethodInvoker)delegate()
                {
                    Delete(tblSource, strKeyFields, oValues);

                });
            }
            else
            {
                Delete(tblSource, strKeyFields, oValues);
            }
        }

        public static List<int> GetCheckedRow(DataGridView tblSource, string strCheckColumnName)
        {
            List<int> lstChecked = new List<int>();
            bool isContainsColumn = false;

            for(int i = 0; i < tblSource.Columns.Count; i++)
                if (tblSource.Columns[i].Name == strCheckColumnName)
                {
                    isContainsColumn = true;
                    break;
                }

            if (isContainsColumn == false)
                return lstChecked;

            for (int i = 0; i < tblSource.Rows.Count; i++)
            {
                if (((DataGridViewCheckBoxCell)tblSource.Rows[i].Cells[strCheckColumnName]).Value == TRUE_VALUE)
                    lstChecked.Add(i);
            }

            return lstChecked;
        }

        public static void SetCheckColumnValue(DataGridView tblSource, string strCheckColumnName, int iRowIndex, bool isChecked)
        {
            ((DataGridViewCheckBoxCell)tblSource.Rows[iRowIndex].Cells[strCheckColumnName]).Value = isChecked ? TRUE_VALUE : FALSE_VALUE;
            tblSource.Rows[iRowIndex].Cells[strCheckColumnName].Value = isChecked ? TRUE_VALUE : FALSE_VALUE;
        }
        public static void DisableSort(DataGridView tblSource)
        {
            for (int i = 0; i < tblSource.Columns.Count; i++)
                tblSource.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable;
        }

        public static DataGridViewCheckBoxColumn CreateCheckBoxCell(string strColumnName, string strHeaderText)
        {
            return CreateCheckBoxCell(strColumnName, strHeaderText, 20);
        }
        public static DataGridViewCheckBoxColumn CreateCheckBoxCell(string strColumnName, string strHeaderText, int iWidth)
        {
            DataGridViewCheckBoxColumn checkBox = new DataGridViewCheckBoxColumn();
            checkBox.Name = strColumnName;
            checkBox.HeaderText = strHeaderText;
            checkBox.Width = iWidth;
            checkBox.FalseValue = FALSE_VALUE;
            checkBox.TrueValue = TRUE_VALUE;
            return checkBox;
        }
    }
}
